接下来我们来DIY另外一个重要的模块defrred延迟对象,这当然与源码有些许的不同,然而这并不重要。
基础包上要进行扩展了,输入命令:
1 | MODULES="zepto event ajax deferred callbacks" npm run dist |
代码挂在我的github上,对应文件夹v0.6.1。
https://github.com/zrysmt/DIY-zepto
1.示例Demo
示例1:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26$.ajax({
type: 'GET',
// type: 'POST',
url: '/projects.json',
dataType: 'json',
timeout: 300,
success: function(data) {
console.log(data);
},
error: function(xhr, type) {
alert('Ajax error!');
}
}).done(function() {
console.info("done");
}).fail(function() {
console.info("fail");
}).always(function() {
console.info("always");
}) //then 三个参数 第一个是成功后回掉,第二个是失败,第三个是运行中
.then(function() {
console.info("then1");
}, function() {
console.info("then2");
}, function() {
console.info("then3");
});
成功后结果:
1 | //done always then1 |
失败后结果:
1 | //alert('Ajax error!') fail always then2 |
示例2:1
2
3
4
5
6
7
8
9
10
11var wait = function(dtd) {
var dtd = $.Deferred(); //在函数内部,新建一个Deferred对象
var tasks = function() {
alert("执行完毕!");
dtd.resolve(); // 改变Deferred对象的执行状态
};
setTimeout(tasks, 5000);
return dtd.promise(); // 返回promise对象
// 返回dtd.promise 因其没有resolve和reject方法,所以在外面不能该调用这两个方法改变状态
};
1 | $.when(wait()).done(function() { |
或者:1
2
3
4
5$.Deferred(wait).done(function() {
alert("哈哈,成功了!");
}) .fail(function() {
alert("出错啦!");
});
2.整体结构
1 | var DeferredMod = function($) { |
3.Promise规范
由于deferred是基于Promise规范,我们首先需要理清楚Promises/A+是什么。
它的规范内容大致如下
- 一个promise可能有三种状态:等待(pending)、已完成(fulfilled)、已拒绝(rejected)
- 一个promise的状态只可能从“等待”转到“完成”态或者“拒绝”态,不能逆向转换,同时“完成”态和“拒绝”态不能相互转换
- promise必须实现then方法(可以说,then就是promise的核心),而且then必须返回一个promise,同一个promise的then可以调用多次,并且回调的执行顺序跟它们被定义时的顺序一致
- then方法接受两个参数,第一个参数是成功时的回调,在promise由“等待”态转换到“完成”态时调用,另一个是失败时的回调,在promise由“等待”态转换到“拒绝”态时调用。同时,then可以接受另一个promise传入,也接受一个“类then”的对象或方法,即thenable对象
伪代码实现:
1 | //初始化: 等待状态 pending |
4.Deferred函数
1 | function Deferred(func) { |
- 这里需要重点注意的是:promise和deferred的关系:
promise只包含执行阶段的方法always(),then(),done(),fail(),progress()及辅助方法state()、promise()等。
deferred则在继承promise的基础上(第5部分:promise.promise(deferred)
),增加切换状态的方法,resolve()/resolveWith(),reject()/rejectWith(),notify()/notifyWith()
所以称promise是deferred的只读副本
- 赋予resolve、reject、notify真正的含义是在
then
中
1 | //切换的状态是resolve成功/reject失败 |
- 提供的
deferred.promise()
方法的作用是,在原来的Deferred 对象上返回另一个 Deferred 对象,即受限制的 Promise 对象,受限制的 Promise 对象只开放与改变执行状态无关的方法(比如done()方法和fail()方法),屏蔽与改变执行状态有关的方法(比如resolve()方法和reject()方法),从而使得执行状态不能被改变
5.给deferred添加切换状态方法
1 | //给deferred添加切换状态方法 |
6.$.when
1 | /** |
示例可以见第一部分示例2
全部代码挂在我的github上,本博文对应文件夹v0.6.x。
https://github.com/zrysmt/DIY-zepto
参考阅读: